Chapter 17

Security and Data Storage

Session 17

Learning Objectives

By the end of this chapter, you will be able to:

1

Principles of Mobile App Security

  • Minimize sensitive data collection and retention.
  • Assume client devices can be compromised and avoid trusting client-only checks.
  • Use defense in depth: encrypt data at rest, use TLS for transport, validate inputs server-side, and apply least privilege for permissions.
  • Fail securely by showing minimal error details and avoiding leak of internal state.
2

Transport Security and APIs

  • Require HTTPS with strong TLS configuration and HSTS on servers.
  • Enforce certificate validation; prefer platform TLS stacks and avoid custom TLS implementations.
  • Use short-lived access tokens and refresh tokens for sessions.
  • Validate and sanitize all server inputs; do not rely on client validation for authorization or rate-limiting.
  • Apply server-side rate limits, parameter validation, and strict CORS/origin rules where web access applies.
3

Authentication and Tokens

  • Use OAuth2 or OpenID Connect when integrating third-party identity providers.
  • Store tokens securely; treat refresh tokens as highly sensitive.
  • Implement refresh token rotation and revoke tokens on suspicious activity.
  • Prefer Authorization Code Flow with PKCE for mobile apps rather than implicit flows.
  • Validate token audience, issuer, expiry, and scopes on each API call.

Token Best Practices

  • Never hard-code secrets, client IDs, or private keys in the app binary.
  • Limit token scope to minimum privileges required by the client.
  • Implement silent re-authentication and clear UX when user session expires.
4

Local Storage Options and Trade-offs

  • Key-value small secrets: use secure platform storage (iOS Keychain, Android EncryptedSharedPreferences / Keystore).
  • Structured local caching: use encrypted database (SQLCipher for sqflite or encrypted_preferences) when storing sensitive user records.
  • File storage: encrypt files before writing and restrict file permissions; avoid storing sensitive data in public external storage.
  • Light ephemeral cache: use SharedPreferences for non-sensitive settings only.

Selection Guide

  • Secrets and tokens → Keychain / EncryptedSharedPreferences.
  • Offline data with sensitivity → Encrypted database or file encryption.
  • Non-sensitive UI state → SharedPreferences or local JSON cache.
5

Encryption and Key Management

  • Use platform-backed key stores so keys are hardware-protected when available.
  • Derive keys using secure KDFs when needed; avoid shipping static symmetric keys.
  • Rotate keys and provide migration paths for encrypted data when keys change.
  • For end-to-end encryption, manage keys server-assisted or user-derived with secure passphrases; never store raw private keys unencrypted on device.

Encryption Checklist

  • Use AES-GCM or ChaCha20-Poly1305 for authenticated encryption.
  • Use proper IV/nonce handling and unique nonces per encryption operation.
  • Store metadata (algorithm, version) with ciphertext to support future migrations.
6

Secure Coding Practices

  • Validate all inputs and avoid unsafe parsing of JSON or binary.
  • Avoid reflection or dynamic code execution that could increase attack surface.
  • Sanitize strings before sending to native components or webviews.
  • Minimize and review third-party dependencies; keep them up to date and audit for vulnerabilities.
  • Use static analysis tools and linters that identify unsafe patterns and potential leaks.

Key Patterns

  • Principle of least privilege for Android permissions; request runtime permissions contextually.
  • Use ProGuard / R8 for release builds to obfuscate code and reduce straightforward reverse-engineering.
  • Strip debug symbols and disable developer features in production builds.
7

Protecting Secrets and API Keys

  • Never embed API keys or secrets directly in source code or resources.
  • Use backend proxying for privileged operations so the app talks to your server, which holds secrets.
  • If third-party API keys must be on-device, restrict them via server-side usage restrictions, domain/app signing constraints, and short-lived tokens where possible.
  • Use environment-specific configuration and CI secrets management for build-time credentials.
8

Secure Handling of User Data and Privacy

  • Collect only necessary user data and provide clear consent dialogs.
  • Follow regional privacy regulations (GDPR, CCPA) for data subject rights like deletion and export.
  • Provide in-app privacy settings and a mechanism to delete cached or uploaded user data.
  • Use anonymization and minimal retention windows for analytics and logs.
9

Network and Backend Validation Patterns

  • Use server-side input validation, authorization checks per endpoint, and data-level masking for logs.
  • Implement per-user authorization checks and object-level ACLs on the server.
  • Validate any client-supplied identifiers before using them in queries or filesystem access to avoid injection and traversal attacks.
10

Secure Updates and Integrity Checks

  • Use platform app stores for signed distribution; require code signing and verify signatures where possible.
  • Consider using binary attestation or safety APIs to detect tampered environments if your threat model requires it.
  • For OTA content or config fetched from the network, sign payloads and verify signatures before applying.
11

Logging, Error Handling, and Monitoring

  • Avoid logging sensitive data (passwords, tokens, PII).
  • Centralize error reporting with filters that redact sensitive fields before sending.
  • Implement anomaly detection and monitoring on the backend to detect unusual behavior or abuse.
  • Provide incident response steps and a revoke mechanism for compromised credentials.
12

Platform-Specific Notes

  • iOS: use Keychain with access control flags (biometric, device passcode). Configure App Transport Security (ATS) and associated domains for Universal Links.
  • Android: use EncryptedSharedPreferences or Keystore for key material and avoid storing secrets in plain SharedPreferences. Use Network Security Config to pin certificates if appropriate.
  • Both: prefer platform APIs for cryptography and secure storage over custom implementations.
13

Testing Security

  • Threat model and risk assessment to prioritize protections.
  • Run static application security testing (SAST), dependency vulnerability scans, and dynamic tests (DAST) against backend endpoints.
  • Perform penetration testing for high-risk apps and consider bug bounty or third-party audits for production systems.
  • Automated security checks in CI for dependency vulnerabilities and secret scanning.
14

Backup, Migration, and Data Lifecycle

  • Encrypt backups containing sensitive data or avoid storing sensitive data in backups altogether.
  • Provide migration scripts when changing data schemas or encryption approaches.
  • Implement clear retention policies and deletion routines for user-requested data removal.
15

Practical Recommendations and Quick Setup

  • Use a secure storage plugin (flutter_secure_storage) for tokens and small secrets.
  • Use an encrypted DB package or platform-backed encryption for persisted user data.
  • Implement Authorization Code with PKCE for authentication flows.
  • Centralize networking in a service layer with retry, backoff, and error normalization.
  • Regularly run dependency audits and pin package versions in CI.
16

Exercises

1. Token storage and refresh

Implement secure token storage using platform-backed secure storage. Simulate token expiry and implement refresh with PKCE flow placeholders.

2. Encrypted local cache

Build a small data cache using an encrypted SQLite wrapper or file-level AES-GCM encryption. Demonstrate read, write, and migration when key version changes.

3. Threat model and checklist

Produce a one-page threat model for your app listing assets, threats, mitigations, and residual risks. Use it to prioritize two security improvements to implement.